﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Uco.Models;
using Telerik.Web.Mvc.UI;
using System.Collections;
using System.Data;
using System.Reflection;
using System.Web.Security;
using Uco.Infrastructure;
using System.Globalization;

namespace Uco.Areas.Admin.Controllers
{
    [Authorize]
    public class MainController : BaseAdminController
    {

        #region AbstractPageEdit

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult View(int id)
        {
            if (SF.GetMenuRepository().Count(r => r.ID == id) > 0)
            {
                AbstractPage ap = SF.LoadPage(SF.GetMenuRepository().First(r => r.ID == id).SeoUrlName);
                return View(ap);
            }
            return View();
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult CreateList(int id)
        {
            if (id == 0) return RedirectToAction("Index");
            ViewBag.id = id;
            return View(GetChildClasses(id));
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult CreateList(int MetadataToken, int id)
        {
            if (id == 0) return RedirectToAction("Index");
            if (MetadataToken != 0)
            {
                foreach (Type item in GetChildClasses(id))
                {
                    if (MetadataToken == item.MetadataToken) return RedirectToAction("Create", new { MetadataToken = item.MetadataToken, id = id });
                }
            }
            ViewBag.id = id;
            return View(GetChildClasses(id));
        }

        public List<Type> GetChildClasses(int id)
        {
            List<Type> childClasses = new List<Type>();

            AbstractPage ap = SF.LoadPage(SF.GetMenuRepository().First(r => r.ID == id).SeoUrlName);

            Type ParentClass = ap.GetType();
            foreach (Type item in SF.GetAbstractPageChildClasses())
            {
                if (SF.GetTypeRestrictParentsAttribute(item).Contains(ParentClass.Name)) childClasses.Add(item);
            }
            return childClasses;
        }

        public object GetClassByToken(int MetadataToken, int id)
        {
            object AbstractClass;
            if (MetadataToken != 0)
            {
                foreach (Type item in GetChildClasses(id))
                {
                    if (MetadataToken == item.MetadataToken)
                    {
                        AbstractClass = Activator.CreateInstance(item);
                        return AbstractClass;
                    }
                }
            }
            return null;
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Create(int id, int MetadataToken)
        {
            ViewBag.id = id;
            ViewBag.MetadataToken = MetadataToken;
            return View(GetClassByToken(MetadataToken, id));
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(AbstractPage ap, int id)
        {
            if (ModelState.IsValid)
            {
                ap.ParentID = id;
                if (ap.SeoUrlName == null || ap.SeoUrlName == "") ap.SeoUrlName = Uco.Infrastructure.SF.CleanUrl(ap.Title);
                else ap.SeoUrlName = Uco.Infrastructure.SF.CleanUrl(ap.SeoUrlName);

                if (SF.GetMenuRepository().Count(r => r.SeoUrlName == ap.SeoUrlName) != 0)
                {
                    ModelState.AddModelError("SeoUrlName", "Title not unic. Please specify Url Name different from title");
                    return View(ap);
                }
                ap.CreateTime = DateTime.Now;
                if (SF.GetMenuRepository().Where(r => r.ParentID == ap.ParentID).Count() == 0) ap.Order = 1;
                else ap.Order = SF.GetMenuRepository().Where(r => r.ParentID == ap.ParentID).Max(r => r.Order) + 1;
                ap.ID = SF.GetMenuRepository().Max(r => r.ID) + 1;
                ap.Save();

                CleanCache.CleanCacheAfterPageEdit();

                return RedirectToAction("View", new { id = ap.ID });
            }
            return View(ap);
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Edit(int id, bool? red)
        {
            if (SF.GetMenuRepository().Count(r => r.ID == id) > 0)
            {
                var ap = SF.LoadPage(SF.GetMenuRepository().Single(r => r.ID == id).SeoUrlName);
                return View(ap);
            }
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(AbstractPage ap, int id, bool? red)
        {
            if (ModelState.IsValid)
            {
                if (ap.SeoUrlName == null || ap.SeoUrlName == "") ap.SeoUrlName = Uco.Infrastructure.SF.CleanUrl(ap.Title);
                else ap.SeoUrlName = Uco.Infrastructure.SF.CleanUrl(ap.SeoUrlName);

                if (SF.GetMenuRepository().Count(r => r.ID != ap.ID && r.RouteUrl == ap.RouteUrl && r.SeoUrlName == ap.SeoUrlName) != 0)
                {
                    ModelState.AddModelError("SeoUrlName", "Title not unic. Please specify Url Name different from title");
                    return View(ap);
                }
                ap.ChangeTime = DateTime.Now;

                if (SF.GetMenuRepository().First(r => r.ID == ap.ID).SeoUrlName != ap.SeoUrlName)
                {
                    AbstractPage toDelete = SF.LoadPage(SF.GetMenuRepository().First(r => r.ID == ap.ID).SeoUrlName);
                    toDelete.Delete();
                }

                ap.Save();

                CleanCache.CleanCacheAfterPageEdit();

                if (red != null && red == true) Response.Redirect(ap.Url);
                else return RedirectToAction("View", new { id = ap.ID });
            }
            return View(ap);
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Delete(int id)
        {
            if (id == 0) RedirectToAction("View", new { id = id });
            if (SF.GetMenuRepository().Count(r => r.ID == id) == 0) throw new NotImplementedException("Can't find page to delete");

            AbstractPage ap = SF.LoadPage(SF.GetMenuRepository().First(r => r.ID == id).SeoUrlName);
            ViewBag.id = id;
            ViewBag.Title = ap.Title;
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(int id, string Title)
        {
            if (id == 0) RedirectToAction("View", new { id = id });
            if (id == 1) throw new NotImplementedException("Can't delete root page");
            
            AbstractPage ap = SF.LoadPage(SF.GetMenuRepository().First(r => r.ID == id).SeoUrlName);
            int parent = ap.ParentID == null ? 0 : (int)ap.ParentID;

            DeleteChildPages(ap);

            ap.Delete();

            CleanCache.CleanCacheAfterPageEdit();

            return RedirectToAction("View", new { id = parent });
        }

        private void DeleteChildPages(AbstractPage ap)
        {
            List<AbstractPage> apl = new List<AbstractPage>();
            foreach (UcoMenuItem item in SF.GetMenuRepository().Where(r => r.ParentID == ap.ID))
            {
                apl.Add(SF.LoadPage(item.SeoUrlName));
            }

            foreach (AbstractPage item in apl)
            {
                DeleteChildPages(item);
                item.Delete();
            }
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ChangeLang(string LangSelectList)
        {
            if (!string.IsNullOrEmpty(LangSelectList)) Session["LangSelectList"] = LangSelectList;
            return RedirectToAction("Index", "Main");
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ChangeSkin(string SkinSelectList)
        {
            if (!string.IsNullOrEmpty(SkinSelectList)) Session["SkinSelectList"] = SkinSelectList;
            return RedirectToAction("Index", "Main");
        }

        #endregion

        #region TreeView

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult _TreeViewLoading(TreeViewItem node)
        {
            int parentId = !string.IsNullOrEmpty(node.Value) ? (int)Convert.ToInt32(node.Value) : 0;

            if (parentId == 0)
            {
                var pages = SF.GetMenuRepository();

                IEnumerable nodes = pages.Where(r => r.ParentID == parentId)
                    .Select(item => new
                    {
                        Text = item.Title,
                        Value = item.ID.ToString(),
                        LoadOnDemand = false,
                        Expanded= true,
                        Enabled = true,
                        ImageUrl = Url.Content(item.Image),
                        ImageHtmlAttributes = new { alt = item.Title },
                        Url = Url.Content(item.Url),
                        Items = pages.Where(r2 => r2.ParentID == item.ID)
                            .Select(item2 => new
                            {
                                Text = item2.Title,
                                Value = item2.ID.ToString(),
                                ImageUrl = Url.Content(item2.Image),
                                ImageHtmlAttributes = new { alt = item2.Title },
                                LoadOnDemand = pages.Count(r => r.ParentID == item2.ID) != 0,
                                Enabled = true,
                                Url = Url.Content(item2.Url)
                            })
                    });
                return new JsonResult { Data = nodes };
            }
            else
            {
                if (SF.GetMenuRepository().Count(r => r.ParentID == parentId) == 0) return new JsonResult { Data = "" };

                var pages = SF.GetMenuRepository();

                IEnumerable nodes = pages.Where(r => r.ParentID == parentId)
                    .Select(item => new
                    {
                        Text = item.Title,
                        Value = item.ID.ToString(),
                        LoadOnDemand = pages.Count(r => r.ParentID == item.ID) != 0,
                        Enabled = true,
                        ImageUrl = Url.Content(item.Image),
                        ImageHtmlAttributes = new { alt = item.Title },
                        Url = Url.Content(item.Url)
                    });
                return new JsonResult { Data = nodes };
            }
        }

        public ActionResult _TreeDrop(int item, int destinationitem, string position)
        {
            AbstractPage ItemPage = SF.LoadPage(SF.GetMenuRepository().First(r => r.ID == item).SeoUrlName);
            AbstractPage DestinationItemPage = SF.LoadPage(SF.GetMenuRepository().First(r => r.ID == destinationitem).SeoUrlName);
			
			if (ItemPage.ParentID == 0) return Content("false");

            if (position == "over")
            {
                Type t = ItemPage.GetType();
                if (GetChildClasses(destinationitem).Contains(t))
                {
                    ItemPage.ParentID = destinationitem;
                    ItemPage.Save();

                    CleanCache.CleanCacheAfterPageEdit();

                    return Content("true");
                }
                else
                {
                    return Content("false");
                }
            }
            else if (position == "before")
            {
                if (DestinationItemPage.ID == 1) return Content("false");
                if (GetChildClasses((int)DestinationItemPage.ParentID).Contains(ItemPage.GetType()))
                {
                    ItemPage.ParentID = DestinationItemPage.ParentID;
                    ItemPage.Order = DestinationItemPage.Order;
                    ItemPage.Save();

                    List<AbstractPage> apl = new List<AbstractPage>();
                    
                    foreach (UcoMenuItem aplItem in SF.GetMenuRepository().Where(r => r.ParentID == (int)DestinationItemPage.ParentID && r.Order >= DestinationItemPage.Order && r.ID != (int)ItemPage.ID))
                    {
                        apl.Add(SF.LoadPage(aplItem.SeoUrlName));
                    }

                    foreach (AbstractPage item2 in apl)
                    {
                        item2.Order = item2.Order + 1;
                        item2.Save();
                    }


                    CleanCache.CleanCacheAfterPageEdit();

                    return Content("true");
                }
                else
                {
                    return Content("false");
                }
            }
            else if (position == "after")
            {
                if (DestinationItemPage.ID == 1) return Content("false");
                if (GetChildClasses((int)DestinationItemPage.ParentID).Contains(ItemPage.GetType()))
                {

                    List<AbstractPage> apl = new List<AbstractPage>();

                    foreach (UcoMenuItem aplItem in SF.GetMenuRepository().Where(r => r.ParentID == (int)DestinationItemPage.ParentID && r.Order >= DestinationItemPage.Order && r.ID != (int)DestinationItemPage.ID))
                    {
                        apl.Add(SF.LoadPage(aplItem.SeoUrlName));
                    }

                    foreach (AbstractPage item2 in apl)
                    {
                        item2.Order = item2.Order + 2;
                        item2.Save();
                    }

                    ItemPage.ParentID = DestinationItemPage.ParentID;
                    ItemPage.Order = DestinationItemPage.Order + 1;
                    ItemPage.Save();

                    CleanCache.CleanCacheAfterPageEdit();

                    return Content("true");
                }
                else
                {
                    return Content("false");
                }
            }

            return Content("false");
        }

        [HttpPost]
        public ActionResult _AjaxLoadingParent(string text)
        {
            var l = SF.GetMenuRepository();
            return new JsonResult { Data = new SelectList(l.ToList(), "ID", "Title") };
        }

        #endregion
        
        #region Other

        public ActionResult LogOut()
        {
            Session.Clear();
            FormsAuthentication.SignOut();
            if (!Response.IsRequestBeingRedirected) Response.Redirect("~/");
            return RedirectToAction("Index");
        }

        #endregion
    }
}
